package us.gaaoc.framework.dao.persistenceLogic;

/**
 * 
 */
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;

import us.gaaoc.framework.model.Address;
import us.gaaoc.framework.model.AddressCategory;
import us.gaaoc.framework.model.AddressType;
import us.gaaoc.framework.model.Attorney;
import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.CaseRecordEventType;
import us.gaaoc.framework.model.CaseRecordHistory;
import us.gaaoc.framework.model.CaseRecordStatus;
import us.gaaoc.framework.model.CaseRecordType;
import us.gaaoc.framework.model.Court;
import us.gaaoc.framework.model.CourtEventType;
import us.gaaoc.framework.model.CourtEvents;
import us.gaaoc.framework.model.LegalPreparer;
import us.gaaoc.framework.model.LocalCaseCategory;
import us.gaaoc.framework.model.LocalCaseDivision;
import us.gaaoc.framework.model.LocalCaseFilingType;
import us.gaaoc.framework.model.LocalCaseType;
import us.gaaoc.framework.model.OrgParticipants;
import us.gaaoc.framework.model.Organizations;
import us.gaaoc.framework.model.ParticipantRelationship;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonAddress;
import us.gaaoc.framework.model.PersonOrganizations;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.util.DateUtil;
import us.gaaoc.framework.util.Encrypt;
import us.gaaoc.framework.util.LocalCaseInformation;
import us.gaaoc.framework.webapp.backingbeans.BaseBackingBean;

/**
 * @author Michael Alexandrou August 14th, 2007
 * 
 */
/**
 * @author Sukhada Tapshalkar
 *
 * Dec 14, 2007
 *
 * GAJE_BibbCounty_2.0
 *
 */
public class PersistInfoIntoCaseRecord extends BaseBackingBean {

	/**
	 * serialVersionUID 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Properties
	 */
	private Date courtDate;
	private static final Logger LOG = Logger.getLogger(PersistInfoIntoCaseRecord.class);

	/**
	 * Constructor
	 * 
	 */
	public PersistInfoIntoCaseRecord() {

	}

	/**
	 * @return the courtDate
	 */
	public Date getCourtDate() {
		return courtDate;
	}

	/**
	 * @param courtDate
	 *            the courtDate to set
	 */
	public void setCourtDate(Date courtDate) {
		this.courtDate = courtDate;
	}

	/**
	 * This method creates a case record given a court. It assumes that within a
	 * court a case record has a unique uuid
	 * 
	 * @param c
	 * @return CaseRecord
	 */
	/*
	public CaseRecord createCaseRecord(Court c) {

		CaseRecordStatus crSt = new CaseRecordStatus();
		CaseRecordType crT = new CaseRecordType();
		LocalCaseDivision localCaseDivision = new LocalCaseDivision();
		LocalCaseType localCaseType = new LocalCaseType();
		
		crT = this.getModelFacade().findCaseRecordTypeByCode(1);
		// TODO pull court configuration from database
		// Set local codes based on court
		
		LocalCaseInformation inf = new LocalCaseInformation();
		inf.populateLocalCaseInformation(c, this.getModelFacade());
		
		localCaseDivision = inf.getLocalCaseDivision();
		localCaseType = inf.getLocalCaseType();
		LocalCaseCategory localCaseCategory = inf.getLocalCaseCategory();
		LocalCaseFilingType localCaseFilingType = inf.getLocalCaseFilingType();
		
		/*
		 * Pseudo Code for dealing with Contempts versus Complaint/Petitions for
		 * Establishment cases
		 * 
		 * There needs to be a way to determine if the "Contempt" or
		 * "Establishment" Button was clicked on to determine which type of
		 * filing is being created to be able to correctly insert the right code
		 * into Sustain.
		 */
		/*
		 * if (click on contempt) { LocalCaseFilingType localCaseFilingType =
		 * this.getModelFacade().findLocalCaseFilingTypeByCourtandCode(c,
		 * "121196"); }else { LocalCaseFilingType localCaseFilingType =
		 * this.getModelFacade().findLocalCaseFilingTypeByCourtandCode(c,
		 * "121110"); }
		 
		Date instanciationDate = DateUtil.getCurrentDate();
		Date submittedDate = DateUtil.getCurrentDate();
		CaseRecord cr = this.getModelFacade().createCaseRecord(instanciationDate, submittedDate,
				crSt, crT, c, localCaseCategory, localCaseDivision, localCaseFilingType, localCaseType, c.getUuid());
		return this.getModelFacade().insertCaseRecord(cr, c.getUuid());
	}
*/
	
	public CaseRecord createCaseRecord(Court c, int externalCaseCategoryCode) {
		
		String courtUuid = c.getUuid();
		
		CaseRecordStatus crSt = new CaseRecordStatus();
		crSt = this.getModelFacade().findCaseRecordStatusByCode(7);

		CaseRecordType crT = new CaseRecordType();
		crT = this.getModelFacade().findCaseRecordTypeByCode(1);
		
		LocalCaseDivision localCaseDivision = new LocalCaseDivision();
		LocalCaseType localCaseType = new LocalCaseType();
		LocalCaseFilingType localCaseFilingType = null;
		LocalCaseCategory localCaseCategory = null;

		LocalCaseInformation inf = new LocalCaseInformation();
		inf.populateFromExternalCaseCategoryCode(c, externalCaseCategoryCode, this.getModelFacade());
		localCaseDivision = inf.getLocalCaseDivision();
		localCaseType = inf.getLocalCaseType();
		localCaseFilingType = inf.getLocalCaseFilingType();
		localCaseCategory = inf.getLocalCaseCategory();
		
		Date instantiationDate = DateUtil.getCurrentDate();
		Date submittedDate = DateUtil.getCurrentDate();
		
		CaseRecord cr = this.getModelFacade().createCaseRecord(instantiationDate,submittedDate,crSt,crT,c,
				localCaseCategory,localCaseDivision,localCaseFilingType,localCaseType, courtUuid);
		
		
		
		cr.setCaseRecordAction(this.getModelFacade().getCaseRecordActionsById(externalCaseCategoryCode));
		
		return (CaseRecord) this.getModelFacade().insertCaseRecord(cr, courtUuid);

	}
	
	/**
	 * This is the helper method to set the values for the organization participants and 
	 * save to the database.
	 * @param cr
	 */
	private void persistInitiatingPartyOrg(CaseRecord cr, 
			String initiatingPartyOrgUuid) {
		OrgParticipants orgP = new OrgParticipants();
		/*
		 Organizations org = this.getModelFacade().findOrganizationById(
				"initiatingPartyOrganizationUuid");
		*/
		Organizations org = this.getModelFacade().findOrganizationById(
				initiatingPartyOrgUuid);
		orgP.setOrganizations(org);
		orgP.setCaseRecord(cr);
		ParticipantRelationship relation = this.getModelFacade()
				.findParticipantRelationship(1);
		orgP.setRelationship(relation);
		this.getModelFacade().insertOrgParticipants(orgP);
	}
	
	/**
	 * This is the helper method which sets the values for the person participant as 
	 * initiating party attorney and then saves to the database
	 * @param caseRecord
	 */
	private void persistInitiatingPartyAttorneyAsPersonParticipant(
			CaseRecord caseRecord, Person personFiler) {
		//Attorney attorney = new Attorney();
	

		PersonOrganizations po = this.getModelFacade().findPersonOrganizationByCourtAndPerson(personFiler, caseRecord.getCourt().getUuid());
			
		LOG.debug("The personOrganization is " + po.getUuid());
		LOG.debug("The organization is " + po.getOrganization().getUuid());
		
		LegalPreparer lp;
		List<LegalPreparer> lpl = this.getModelFacade().getLegalPreparers(personFiler, po.getOrganization());
		if(lpl.size() == 1)
		{
			lp =lpl.get(0);
		}else{
			return;
		}
		//LegalPreparer lp = new LegalPreparer();
		//lp = (LegalPreparer) this.getModelFacade().findLegalPreparerByPersonAndOrg(personFiler, po.getOrganization().getUuid());
		
		LOG.info("The uuid of the legalPreparer is .." + lp.getUuid());
		//LOG.info("The attorney uuid is .." + lp.getAttorney().getUuid());
		
		//attorney = lp.getAttorney();
		PersonParticipants pp = new PersonParticipants();
		ParticipantRelationship pr = new ParticipantRelationship();
		
		pr = this.getModelFacade().findParticipantRelationship(4);
		
		pp.setCaseRecord(caseRecord);
		
		//Attorney at = this.getModelFacade().findAttorneyByLegalPreparerUuid(lp.getUuid());
		Attorney at = lp.getAttorney();
		
		//pp.setPerson(this.getModelFacade().findAttorneyByBarIDAndOrgAsPerson
		//				(attorney.getBarID(),attorney.getOrganization().getUuid()));
		//pp.setPerson(this.getModelFacade().getNullAttorney(lp.getOrganization()).getPerson());
		pp.setPerson(at.getPerson());
		pp.setRelationship(pr);
		
		this.getModelFacade().insertPersonParticipants(pp);
		LOG.info("Attorney is now associated with case record");
	}

	/**
	 * This is the helper method to the values for the filer and then saves data into the 
	 * person participant table as filer
	 * @param caseRecord
	 */
	private void persistFilerAsPersonParticipant(CaseRecord caseRecord) {
		Person personFiler = new Person();
		personFiler = (Person) this.getFacesContext().getExternalContext()
				.getSessionMap().get("person");
		PersonParticipants pp = new PersonParticipants();
		ParticipantRelationship pr = new ParticipantRelationship();
		pr = this.getModelFacade().findParticipantRelationship(6);
		pp.setCaseRecord(caseRecord);
		pp.setPerson(personFiler);
		pp.setRelationship(pr);
		this.getModelFacade().insertPersonParticipants(pp);
		LOG.info("Filer is now associated with case record");
	}

	/**
	 * Helper method to save the data into the case record history table in database
	 * @param personSigned
	 * @param caseRecord
	 */
	private void persistCaseRecordHistory(Person personSigned, CaseRecord caseRecord) {
		CaseRecordEventType cret = new CaseRecordEventType();
		cret = this.getModelFacade().findCaseRecordEventType(12);
		CaseRecordHistory crh = new CaseRecordHistory();
		crh.setPerson(personSigned);
		crh.setCaseRecord(caseRecord);
		crh.setEventID(cret.getCode());
		crh.setEventDateTime(DateUtil.getCurrentDate());
		crh.setEventType(cret);
		this.getModelFacade().insertCaseRecordHistory(crh);
		LOG.info("the case record history is persisted now...");
	}

	/**
	 * Helper method which helps to save the data such as eventType, caseRecord and eventType 
	 * into the court events table 
	 * @param caseRecord
	 * @param object
	 */
	private void persistCourtEvents(CaseRecord caseRecord, Object object) {
		CourtEvents ce = new CourtEvents();
		CourtEventType cet = new CourtEventType();
		cet = this.getModelFacade().findCourtEventType(1);
		List<CourtEventType> listCrt = new ArrayList<CourtEventType>();
		listCrt.add(cet);
		ce.setEventType(cet);
		ce.setCaseRecord(caseRecord);
		ce.setEventTime(this.courtDate);
		this.getModelFacade().insertCourtEvents(ce);

	}

	/* working on this method saving the original copy of method and modifying the duplicate copy of this method.
	 * Rather than sending the PersonAddres we have to send the Address to check whether it is duplicate or not
	 * as our personAddress table has changed
	 
	private void persistAssociationPersonToCaseRecord(CaseRecord caseRecord,
			Person person, PersonAddress address, String ssn,
			int personParticipantsRelationshipCode, int addressType) {

		Person p = new Person();
		//if (!ssn.equalsIgnoreCase("")) {
		if(ssn != null){
			
			 * ******************************************************************
			 * Security Hazard to put SSN in log files
			 * 
			 * Use a debug statement when debugging locally
			 * and deleting log files after end of debugging.
			 * *****************************************************************
			 
			p = this.getModelFacade().findPersonByHashedSSN(
					Encrypt.encrypt(ssn));
			if (p != null) {
				LOG.info("Person " + p.getFirstName() + " " + p.getLastName()
						+ " already in data base!");
				PersonParticipants pp = new PersonParticipants();
				ParticipantRelationship pr = new ParticipantRelationship();
				pr = this.getModelFacade().findParticipantRelationship(
						personParticipantsRelationshipCode);
				//If Person already exist in the database then check for the address if 
				//it is same then don't update it otherwise update with the new address
				
				//AddressType at = new AddressType();
				//at = this.getModelFacade().findAddressType(addressType);
				int addressCategoryCode = 1;		//for physical address
				AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
				int addressTypeCode = 1;		//for primary contact
				AddressType addressTyp = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);

				Address addressInstance = new Address();
				addressInstance = this.getModelFacade().findAddress(p,addressTyp);
				
				addressInstance = this.getModelFacade().findAddress(addressTyp);
				
				//at = this.getModelFacade().findAddressType(addressType);
				boolean isSameAddress = false;
				
				if (address != null) {
					isSameAddress = this.checkForSameAddress(addressInstance,address);
					
					PersonAddress pa = new PersonAddress();
					pa.setStreetFullText(address.getStreetFullText());
					pa.setCityName(address.getCityName());
					pa.setPerson(p);
					pa.setState(address.getState());
					pa.setZipCode(address.getZipCode());
					pa.setAddressType(at);
					this.getModelFacade().insertPersonAddress(pa);
					
				} 
				pp.setCaseRecord(caseRecord);
				pp.setPerson(p);
				pp.setRelationship(pr);
				this.getModelFacade().insertPersonParticipants(pp);
			} else {
				LOG.info("SSN  in the data file but not in data base, check by name and dob");
				List<Person> personOfSameNameAndSameDOBList = new ArrayList<Person>();
				if (person.getDob() != null) {
					personOfSameNameAndSameDOBList = this.getModelFacade()
							.findPersonListByNameAndByDOB(person.getFirstName(),
									person.getMiddleName(), person.getLastName(),
									person.getDob());
				}

				if (personOfSameNameAndSameDOBList.size() != 0) {
					System.out
							.println("There are people with the same name and the same date of birth ");
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					//if person already exists in database then therre is no need to add again the address
					//AddressType at = new AddressType();
					//at = this.getModelFacade().findAddressType(addressType);
					if (address != null) {
						PersonAddress pa = new PersonAddress();
						pa.setStreetFullText(address.getStreetFullText());
						pa.setCityName(address.getCityName());
						pa.setPerson(personOfSameNameAndSameDOBList.get(0));
						pa.setState(address.getState());
						pa.setZipCode(address.getZipCode());
						pa.setAddressType(at);
						this.getModelFacade().insertPersonAddress(pa);
					} 
					pp.setCaseRecord(caseRecord);
					pp.setPerson(personOfSameNameAndSameDOBList.get(0));
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				} else {
					// create person from scratch
					Person targetPerson = new Person();
					targetPerson.setFirstName(person.getFirstName());
					targetPerson.setMiddleName(person.getMiddleName());
					targetPerson.setLastName(person.getLastName());
					targetPerson.setSuffixName(person.getSuffixName());
					targetPerson.setDob(person.getDob());
					LOG.info("persisting a person object...");
					this.getModelFacade().makePersistent(targetPerson);
					
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					//AddressType at = new AddressType();
					//at = this.getModelFacade().findAddressType(addressType);
					//List <AddressType>addressTypeList = new ArrayList<AddressType>();
					//addressTypeList.add(at);
					int addressCategoryCode = 1;	//for physicalAddress
					AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
					int addressTypeCode = 1;		//for promaryContactInformation
					AddressType addressType2 = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);
					Address address2 = null;//this.getModelFacade().findAddress(addressType2);
					if (address2 != null) {
						PersonAddress pa = new PersonAddress();
						
						Address addressToSet = new Address();
						addressToSet.setStreetFullText(address2.getStreetFullText());
						addressToSet.setCityName(address2.getCityName());
						
						addressToSet.setState(address2.getState());
						addressToSet.setZipCode(address2.getZipCode());
											
						pa.setAddress(addressToSet);	
						pa.setPerson(targetPerson);
						//pa.setAddresTypes(addressTypeList);
						this.getModelFacade().insertPersonAddress(pa);
					}
					this.getModelFacade().insertIntoPersonIdHashedSSN(
							targetPerson.getUuid(),
							Encrypt.getInstance().encrypt(ssn));
					pp.setCaseRecord(caseRecord);
					pp.setPerson(targetPerson);
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				}
			}
		} else {
			LOG.info("SSN not in data file, check by name and dob");
			if (person.getDob() != null) {
				List<Person> personOfSameNameAndSameDOBList = new ArrayList<Person>();
				personOfSameNameAndSameDOBList = this.getModelFacade()
						.findPersonListByNameAndByDOB(person.getFirstName(),
								person.getMiddleName(), person.getLastName(),
								person.getDob());
				LOG.debug("The number of people with the name "
						+ person.getFirstName() + " "+person.getMiddleName()+" " + person.getLastName()
						+ " and date of birth " + person.getDob().toString()
						+ " is " + personOfSameNameAndSameDOBList.size());

				if (personOfSameNameAndSameDOBList.size() != 0) {
					System.out
							.println("There are people with the same name and the same date of birth ");
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					//AddressType at = new AddressType();
					//at = this.getModelFacade().findAddressType(addressType);
					
					 * if (address != null) { PersonAddress pa = new
					 * PersonAddress();
					 * pa.setStreetFullText(address.getStreetFullText());
					 * pa.setCityName(address.getCityName());
					 * pa.setPerson(personOfSameNameAndSameDOBList.get(0));
					 * pa.setState(address.getState());
					 * pa.setZipCode(address.getZipCode());
					 * pa.setAddressType(at);
					 * this.getModelFacade().insertPersonAddress(pa); }
					 
					pp.setCaseRecord(caseRecord);
					pp.setPerson(personOfSameNameAndSameDOBList.get(0));
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				} else {
					// create person from scratch
					Person targetPerson = new Person();
					targetPerson.setFirstName(person.getFirstName());
					targetPerson.setMiddleName(person.getMiddleName());
					targetPerson.setLastName(person.getLastName());
					targetPerson.setSuffixName(person.getSuffixName());
					targetPerson.setDob(person.getDob());
					LOG.info("persisting a person object...");
					this.getModelFacade().makePersistent(targetPerson);
					LOG.debug("The uuid of the new person is .."
							+ targetPerson.getUuid());
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					int addressCategoryCode = 1;	//for physical
					AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
					int addressTypeCode = 1;		//for primary contact information
					AddressType addressType2 = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);
					Address address2 = null;//this.getModelFacade().findAddress(addressType2);
					
					AddressType at = new AddressType();
					List<AddressType>addressTypeList = new ArrayList<AddressType>();
					at = this.getModelFacade().findAddressType(addressType);
					addressTypeList.add(at);
					
					if (address != null) {
						PersonAddress pa = new PersonAddress();
						
						pa.setStreetFullText(address.getStreetFullText());
						pa.setCityName(address.getCityName());
						pa.setPerson(targetPerson);
						pa.setState(address.getState());
						pa.setZipCode(address.getZipCode());
						pa.setAddressCategoryType(act);
						
						this.getModelFacade().insertPersonAddress(pa);
					}
					// this.getModelFacade().insertIntoPersonIdHashedSSN(
					// targetPerson.getUuid(),
					// Encrypt.getInstance().encrypt(ssn));
					pp.setCaseRecord(caseRecord);
					pp.setPerson(targetPerson);
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				}
			} else {
				Person personOfSameNameList = new Person();
				personOfSameNameList = this.getModelFacade().findPersonByName(person.getFirstName(), person.getMiddleName(), person.getLastName());
						
				
				if (personOfSameNameList != null) {
					System.out
							.println("There are people with the same name and the same date of birth ");
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					//AddressType at = new AddressType();
					//at = this.getModelFacade().findAddressType(addressType);
					
					 * if (address != null) { PersonAddress pa = new
					 * PersonAddress();
					 * pa.setStreetFullText(address.getStreetFullText());
					 * pa.setCityName(address.getCityName());
					 * pa.setPerson(personOfSameNameAndSameDOBList.get(0));
					 * pa.setState(address.getState());
					 * pa.setZipCode(address.getZipCode());
					 * pa.setAddressType(at);
					 * this.getModelFacade().insertPersonAddress(pa); }
					 
					pp.setCaseRecord(caseRecord);
					pp.setPerson(personOfSameNameList);
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				} else {
					// create person from scratch
					Person targetPerson = new Person();
					targetPerson.setFirstName(person.getFirstName());
					targetPerson.setMiddleName(person.getMiddleName());
					targetPerson.setLastName(person.getLastName());
					targetPerson.setSuffixName(person.getSuffixName());
					//targetPerson.setDob(person.getDob());
					LOG.info("persisting a person object...");
					this.getModelFacade().makePersistent(targetPerson);
					LOG.debug("The uuid of the new person is .."
							+ targetPerson.getUuid());
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					
					int addressCategoryCode = 1;	//for physical
					AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
					int addressTypeCode = 1;		//for primary contact information
					AddressType addressType2 = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);
					Address address2 =null;// this.getModelFacade().findAddress(addressType2);
					
					
					AddressType at = new AddressType();
					List <AddressType>addressTypeList = new ArrayList<AddressType>();
					at = this.getModelFacade().findAddressType(addressType);
					addressTypeList.add(at);
					if (address != null) {
						PersonAddress pa = new PersonAddress();
						
						pa.setStreetFullText(address.getStreetFullText());
						pa.setCityName(address.getCityName());
						pa.setPerson(targetPerson);
						pa.setState(address.getState());
						pa.setZipCode(address.getZipCode());
						pa.setAddressCategoryType(act);
						
						this.getModelFacade().insertPersonAddress(pa);
					}
					// this.getModelFacade().insertIntoPersonIdHashedSSN(
					// targetPerson.getUuid(),
					// Encrypt.getInstance().encrypt(ssn));
					pp.setCaseRecord(caseRecord);
					pp.setPerson(targetPerson);
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				}
			}
		} 
	}
	*/
		

	/*
	 * @TODO still has to work on this functionality
	 */
	/**
	 * @param at
	 * @param address
	 * @return
	 */
	private boolean checkForSameStreetAddress(Address addressInstance, Address address) {
		boolean sameAddress = true;
		String zipCode = null;
		String state = null;
		String cityName = null;
		String streetFullText = null;
		
		
			zipCode = addressInstance.getZipCode();
			state = addressInstance.getState();
			cityName = addressInstance.getCityName();
			streetFullText = addressInstance.getStreetFullText();
		
			if(zipCode.equals(address.getZipCode())) {
				if(state.equals(address.getState())) {
					if(cityName.equals(address.getCityName())) {
						if(streetFullText.equals(address.getStreetFullText())) {
							sameAddress = true;
						}else {
							sameAddress = false;
						}						
					}else {
						sameAddress = false;
					}
				}else {				
					sameAddress = false;
				}
			}else {
				sameAddress = false;
			}		
		
		return sameAddress;
	}
	
	/**
	 * Method to check to see if the address is exactly the same down to the
	 * street extension text.  Useful for urban areas where apartments and 
	 * condos have the same street address, but not the same street extension 
	 * address.
	 * 
	 * @param addressToCheck Address to check
	 * @param addressCheckedAgainst Address to check against for a match
	 * @return True or false boolean to say whether the match was exact or not.
	 */
	private boolean checkForExactAddressMatch(Address addressToCheck, Address addressCheckedAgainst) {
		boolean exactMatch = true;
		
		
		
		String zipCode = addressToCheck.getZipCode();
		String state = addressToCheck.getState();
		String cityName = addressToCheck.getCityName();
		String streetFullText = addressToCheck.getStreetFullText();
		String streetExtensionText = addressCheckedAgainst.getStreetExtensionText();
		
		if(zipCode.equals(addressCheckedAgainst.getZipCode())) {
			if(state.equals(addressCheckedAgainst.getState())) {
				if(cityName.equals(addressCheckedAgainst.getCityName())) {
					if(streetFullText.equals(addressCheckedAgainst.getStreetFullText())) {
						if(streetExtensionText.equals(addressCheckedAgainst.getStreetExtensionText())) {
							exactMatch = true;
						} else {
							exactMatch = false;
						}
					}else {
						exactMatch = false;
					}						
				}else {
					exactMatch = false;
				}
			}else {				
				exactMatch = false;
			}
		}else {
			exactMatch = false;
		}		
		
		return exactMatch;
	}

	
	/**
	 * This method receives the extracted from the data file information and
	 * persists this data
	 */
	public void persistExtractedInfoFromTextFile(Person personSigned, CaseRecord caseRecord,
			Person cus, String cusSSN, Person nonCus, String nonCusSSN,
			Address cusAddress, Address nonCusAddress,
			List<Person> initiatingPartyPersonList,
			List<PersonAddress> initiatingPartyPersonAddressList,
			List<String> initiatingPartyPersonSSNList,
			String initiatingPartyOrgUuid)throws IOException {
		// PersistCaseParticipants pcp = new PersistCaseParticipants();
		if (cusAddress != null) {
			// For custodial, personParticipantsRelationshipCode is 3 and
			// addressType is 1 for physical address
			this.persistAssociationPersonToCaseRecord(caseRecord, cus, cusAddress,
					cusSSN, 3);
		} else {
			this.persistAssociationPersonToCaseRecord(caseRecord, cus, null,
					cusSSN, 3);
		}
		if (nonCusAddress != null) {
			// for non custodial personParticipantsRelationshipCode is 2 and
			// addressType is 1 for physical address
			this.persistAssociationPersonToCaseRecord(caseRecord, nonCus, nonCusAddress,
					nonCusSSN, 2);
		} else {
			this.persistAssociationPersonToCaseRecord(caseRecord, nonCus, null,
					nonCusSSN, 2);
		}
		this.persistInitiatingPartyAttorneyAsPersonParticipant(caseRecord, personSigned);
		this.persistFilerAsPersonParticipant(caseRecord);
		this.persistCaseRecordHistory(personSigned, caseRecord);
		LOG.info("After the persisting ..");
		
		if (this.courtDate != null) {
			this.persistCourtEvents(caseRecord, this.courtDate);
		}
		/*else {
			this.courtDate = new Date();
			this.persistCourtEvents(caseRecord, this.courtDate);
		}
		*/
		if (initiatingPartyPersonList.size() >= 1) {
			Iterator iter = initiatingPartyPersonSSNList.iterator();
			for (Person p  : initiatingPartyPersonList) {
				//for(String ssn : initiatingPartyPersonSSNList) {
				String ssn = null;
				if(iter.hasNext())
				{
					ssn = (String) iter.next();
				}
				this.persistAssociationPersonToCaseRecord(caseRecord, p, null, ssn, 1);
			}
		}
		this.persistInitiatingPartyOrg(caseRecord, initiatingPartyOrgUuid);
	}
	

	/* TODO - This method could use cleaning up and breaking down into smaller
	 * reusable methods.
	 */

	/**
	 * @param caseRecord
	 * @param person
	 * @param addressParsed
	 * @param ssn
	 * @param personParticipantsRelationshipCode
	 * @param addressType
	 */
	private void persistAssociationPersonToCaseRecord(CaseRecord caseRecord,
			Person person,Address addressParsed, String ssn,
			int personParticipantsRelationshipCode) {

		Person p = new Person();
		
		int addressCategoryCode = 1;		//for physical address
		int addressTypeCode = 1;		//for primary contact
		AddressType addressType = this.getAddressType(addressCategoryCode, addressTypeCode);		
		PersonParticipants pp = new PersonParticipants();
		ParticipantRelationship pr = new ParticipantRelationship();
		pr = this.getModelFacade().findParticipantRelationship(personParticipantsRelationshipCode);
		
		/* Does the parsed address exist in the database? */
		Address matchingAddress = new Address();
		if (addressParsed != null){
			matchingAddress = this.getModelFacade().findAddressExactMatch(addressParsed);
		}
		boolean addressExistsInDB = false;
		if (matchingAddress != null 
				&& matchingAddress.getUuid() != null) {
			// If it does exist, set flag to signal that it does
			addressExistsInDB = true;
		}
		
		
		if( ssn != null && !ssn.trim().equalsIgnoreCase("")){
			/*
			 * ******************************************************************
			 * Security Hazard to put SSN in log files
			 * 
			 * Use a debug statement when debugging locally
			 * and deleting log files after end of debugging.
			 * *****************************************************************
			 */
			p= null;//;= this.getModelFacade().findPersonByHashedSSN(
				//	Encrypt.encrypt(ssn));
			
			
			if (p != null) {
				LOG.info("Person " + p.getFirstName() + " " + p.getLastName()
						+ " already in data base!");
				/* TODO - Need to add in update of street extension text if the
				 * street extension text is missing from an address already in 
				 * the database and an address matches other than the street
				 * extension text.
				 */
				/* TODO - Need to run check against all addresses listed for a 
				 * person.
				 */ 
				/*
				 * TODO - Need to check for more than just street address. From
				 * city to city, the street addresses get reused over and over.
				 * 
				 * Method in question is "findPersonAddress(p, streetAddressText"
				 */
				Address addressFromDB = this.getModelFacade().findAddress(p,addressType);
				PersonAddress personAddress = new PersonAddress();
				/*
				 * If Person already exist in the database then check for an 
				 * address associated with that person.  If there is one and it
				 * is same as the one parsed from the data file then don't 
				 * update it, otherwise update the person address associations 
				 * table with the new address as the physical primary contact 
				 * location and change the prior address to simply a personal 
				 * address associated with that person.
				 */						
				
				/* If the person already has an address in the database . . .
				 */
				if(addressFromDB != null){
					boolean isSameStreetAddress = false;
					LOG.debug("There is an address on record for this person.");
					//To solve JIRA issue GAJETWOX-53, an IF block is added
					if (addressParsed != null){
						isSameStreetAddress = this.checkForSameStreetAddress(
							addressFromDB, addressParsed);
					}
					if (isSameStreetAddress) {
						this.checkForExactAddressMatch(addressFromDB, 
								addressParsed);
					}
					/*
					 * . . . but it isn't the one listed for this person . . .
					 */
					if(!isSameStreetAddress) {
						
						if(addressParsed != null) {
							/*  . . . change the type of address for the old address 
							 * to not be the primary contact address for the 
							 * person . . . 
							 */
							String addressInstanceUuid = addressFromDB.getUuid();
							PersonAddress paPrior = this.getModelFacade().findPersonAddress(p, addressInstanceUuid);
							int addressCategoryCode2 = 1;		//for physical address
							int addressTypeCode2 = 2;		//for personal contact
							AddressType addressType2 = this.getAddressType(addressCategoryCode2, addressTypeCode2); 
							String personAddressUuidPrior = paPrior.getUuid();
							// Commit the change of the address Type
							int personAddressTypeUpdateOutcomeCode = 
								this.getModelFacade()
									.updatePersonAddressType(
											personAddressUuidPrior, 
											addressType2);
							
							/* TODO Add in error handling for if the prior 
							 * PersonAddress entry was not successfully updated.
							 * 
							 * Need to go to error recovery routines and then 
							 * finally to manual intervention if no other 
							 * recovery options work.
							 */
							if (personAddressTypeUpdateOutcomeCode == 0) {
								/* . . . then add in the new address as the primary 
								 * contact physical address for the person.
								 */
								LOG.debug("Address: " + personAddressUuidPrior
										+ " was updated to " + addressType2.getUuid());
								personAddress = this.createPersonAddress(p, addressParsed, addressType);
								this.getModelFacade().insertPersonAddress(personAddress);
								pp.setCaseRecord(caseRecord);
								pp.setPerson(p);
								pp.setRelationship(pr);
								this.getModelFacade().insertPersonParticipants(pp);
								
							} else {
								/* If prior address was not updated, then don't
								 * enter the next address. Only enter the other
								 * items that are correctly entered.
								 */ 
								/* *******************************************
								 * TODO This is a temporary fix until better 
								 * error handling routines are in place.
								 * 
								 * New data shouldn't be ignored, but until 
								 * routines to handle error correction are in 
								 * place, this method catches the off chance 
								 * when an new address is available and an error
								 * condition on updating the prior address
								 * occurs.
								 * *******************************************
								 */
							
								LOG.debug("**** Prior Primary Contact Info Not " 
										+ "Updated Correctly for Person " 
										+ "Participant: " + p.getFirstName() 
										+ " " + p.getLastName());
								pp.setCaseRecord(caseRecord);
								pp.setPerson(p);
								pp.setRelationship(pr);
								this.getModelFacade().insertPersonParticipants(pp); 
							}
						}
					}
					/* . . . and the address on record is the same as the one 
					 * parsed, then don't update the address record, and commit 
					 * the other data items.
					 */
						/* TODO this block of code could be a sub routine method
						 * since it is called quite often.
						 */
						pp.setCaseRecord(caseRecord);
						pp.setPerson(p);
						pp.setRelationship(pr);
						this.getModelFacade().insertPersonParticipants(pp);
						
				/* End of if(addressInstance != null) statement */
				} else {	
				/* If the person does not already have an address in the 
				 * database . . .
				 */
						/* Add the address to that person 	*/
						if(addressParsed != null && !addressExistsInDB) {
							/* . . . and the address does not exist in the 
							 * database, then create a new address entry.
							 */
							personAddress = this.createPersonAddress(p, addressParsed, addressType);
							this.getModelFacade().insertPersonAddress(personAddress);
							pp.setCaseRecord(caseRecord);
							pp.setPerson(p);
							pp.setRelationship(pr);
							this.getModelFacade().insertPersonParticipants(pp);
						} else if (addressParsed != null && addressExistsInDB) {
							/* . . . and the address does already exist in the
							 * database, then associate the existing address 
							 * with this person.
							 */
							personAddress = this.createPersonAddress(p, matchingAddress, addressType);
							this.getModelFacade().insertPersonAddress(personAddress);
							pp.setCaseRecord(caseRecord);
							pp.setPerson(p);
							pp.setRelationship(pr);
							this.getModelFacade().insertPersonParticipants(pp);
						} else if (addressParsed == null) {
						    pp.setCaseRecord(caseRecord);
						    pp.setPerson(p);
						    pp.setRelationship(pr);
						    this.getModelFacade().insertPersonParticipants(pp);
						}
				}//end of else
			}//end of if (p != null)}
			else {
				LOG.info("SSN  in the data file but not in data base, check by name and dob");
				List<Person> personOfSameNameAndSameDOBList = new ArrayList<Person>();
				if (person.getDob() != null) {
					personOfSameNameAndSameDOBList = this.getModelFacade()
							.findPersonListByNameAndByDOB(person.getFirstName(),
									person.getMiddleName(), person.getLastName(),
									person.getDob());
				}

				if (personOfSameNameAndSameDOBList.size() != 0) {
					LOG.debug("There are people with the same name and the same date of birth ");
					for(Person personInLoop : personOfSameNameAndSameDOBList) {
						pp.setCaseRecord(caseRecord);
						pp.setPerson(personInLoop);
						pp.setRelationship(pr);
						this.getModelFacade().insertPersonParticipants(pp);
					}
					
				} else {
					PersonParticipants pp1 = this.createPersonAndAssociations(person,ssn, addressParsed, personParticipantsRelationshipCode);
					pp1.setCaseRecord(caseRecord);
					this.getModelFacade().insertPersonParticipants(pp1);
					
					LOG.debug("Created new person participant");
				}
			}//end of else
		}//end off if(ssn != null)
		else {
			LOG.debug("There is no ssn in the data file ");
			if (person.getDob() != null) {
				List<Person> personOfSameNameAndSameDOBList = new ArrayList<Person>();
				personOfSameNameAndSameDOBList = this.getModelFacade()
						.findPersonListByNameAndByDOB(person.getFirstName(),
								person.getMiddleName(), person.getLastName(),
								person.getDob());
			if (personOfSameNameAndSameDOBList.size() != 0) {
					LOG.debug("There are people with the same name and the same date of birth ");
					for(Person personInLoop : personOfSameNameAndSameDOBList) {
						pp.setCaseRecord(caseRecord);
						pp.setPerson(personInLoop);
						pp.setRelationship(pr);
						this.getModelFacade().insertPersonParticipants(pp);
					}//end of for loop
				}//end of if (personOfSameNameAndSameDOBList.size() != 0)
				else {
					PersonParticipants pp1 = this.createPersonAndAssociations(person,ssn, addressParsed, personParticipantsRelationshipCode);
					pp1.setCaseRecord(caseRecord);
					this.getModelFacade().insertPersonParticipants(pp1);
				}//end of else
			}//end of if (person.getDob() != null)
			else {
				LOG.debug("There is no ssn in the data base and there is no dob in the data base" );
				Person personOfSameName = new Person();
				personOfSameName = this.getModelFacade().findPersonByName(person.getFirstName(), person.getMiddleName(), person.getLastName());				
				if (personOfSameName != null) {
					LOG.debug("There are people with the same name and the same date of birth ");
					pp.setCaseRecord(caseRecord);
					pp.setPerson(personOfSameName);
					pp.setRelationship(pr);
					this.getModelFacade().insertPersonParticipants(pp);
				} //end of if (personOfSameName != null) 
				else {
					PersonParticipants pp1 = this.createPersonAndAssociations(person,ssn,addressParsed,personParticipantsRelationshipCode);
					pp1.setCaseRecord(caseRecord);
					this.getModelFacade().insertPersonParticipants(pp1);
					
				}//end of else
			}//end of else
		}// end of else
	}
	
	/**
	 * This is the helper method which creates the PersonParticipants object by passing the Person,ssn,address and 
	 * personParticipants's relationship code
	 * @param person
	 * @param address
	 * @param personParticipantsRelationshipCode
	 * @return
	 */
	@SuppressWarnings("static-access")
	private PersonParticipants createPersonAndAssociations(Person person,String ssn,Address address,int personParticipantsRelationshipCode) {
					// create person from scratch
					String uuid = UUID.randomUUID().toString();
					Person targetPerson = new Person();
					targetPerson.setUuid(uuid);
					targetPerson.setFirstName(person.getFirstName());
					targetPerson.setMiddleName(person.getMiddleName());
					targetPerson.setLastName(person.getLastName());
					targetPerson.setSuffixName(person.getSuffixName());
					//targetPerson.setDob(person.getDob());
					LOG.info("persisting a person object...");
					this.getModelFacade().makePersistent(targetPerson);
					LOG.debug("The uuid of the new person is .."
							+ targetPerson.getUuid());
					if(ssn != null) {						
						this.getModelFacade().insertIntoPersonIdHashedSSN(
								targetPerson.getUuid(),
								Encrypt.getInstance().encrypt(ssn));
						LOG.debug("The uuid of the new PersonHashedSSN is ..");
					}
				
					
					PersonParticipants pp = new PersonParticipants();
					ParticipantRelationship pr = new ParticipantRelationship();
					pr = this.getModelFacade().findParticipantRelationship(
							personParticipantsRelationshipCode);
					
					int addressCategoryCode = 1;		//for physical address
					int addressTypeCode = 1;		//for primary contact
					AddressType addressType = this.getAddressType(addressCategoryCode, addressTypeCode);
					
					if (address != null) {
						PersonAddress pa = this.createPersonAddress(targetPerson, address, addressType);
						this.getModelFacade().insertPersonAddress(pa);
					}	
					pp.setPerson(targetPerson);
					pp.setRelationship(pr);					
					return pp;
		}	 
	
	/**
	 * This method is the helper method to create the PersonAddress object from the address and person objects
	 * @param person
	 * @param address
	 * @param addressType
	 * @return
	 */
	private PersonAddress createPersonAddress(Person person, Address address, AddressType addressType) {
		Address addr = new Address();
		addr.setUuid(UUID.randomUUID().toString());
		addr.setStreetFullText(address.getStreetFullText());
		addr.setStreetExtensionText(address.getStreetExtensionText());
		addr.setCityName(address.getCityName());
		addr.setState(address.getState());
		addr.setZipCode(address.getZipCode());
		this.getModelFacade().insertAddress(addr);						
		PersonAddress pa = new PersonAddress();	
		pa.setUuid(UUID.randomUUID().toString());
		pa.setPerson(person);
		pa.setAddressType(addressType);
		pa.setAddress(addr);
		return pa;
	}
	
	/**
	 * this is the helper method to get the AddressType bby passing addressCategoryCode and addressTypeCode
	 * @param addressCategoryCode
	 * @param addressTypeCode
	 * @return
	 */
	private AddressType getAddressType(int addressCategoryCode, int addressTypeCode ) {
		AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
		AddressType addressType = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);		
		return addressType;
	}
	

		
}